<?php

/**
 * contact : 刘经理 19326416371
 * company : 版权所属 四川北星惯牌科技有限公司
 **/


namespace app\common\manager;

use app\common\constant\Constant;
use app\common\model\Level;
use app\common\model\MoneyLog;
use app\common\model\Store;
use app\common\model\ProfitStatistics;
use app\common\model\StoreAccount;
use app\common\model\StoreMoneyLog;
use think\Db;
use think\Exception;

class StoreAccountManager extends BaseManager
{

    CONST TYPE_REWARD = 1;
    CONST TYPE_REWARD_MESSAGE = '奖励';
    CONST TYPE_FREEZE = 2;
    CONST TYPE_FREEZE_MESSAGE = '冻结';
    CONST TYPE_WITHDRAWAL = 3;
    CONST TYPE_WITHDRAWAL_MESSAGE = '提现';
    CONST TYPE_UNFREEZE = 4;
    CONST TYPE_UNFREEZE_MESSAGE = '解冻';

    CONST TYPE_TEAM = 5;
    CONST TYPE_TEAM_MESSAGE = '组队';

    CONST TYPE_MATCH = 6;
    CONST TYPE_MATCH_MESSAGE = '赛事';

    CONST TYPE_ASSISTANT_REWARD = 7;
    CONST TYPE_ASSISTANT_REWARD_MESSAGE = '助教奖励';

    CONST TYPE_ASSISTANT = 8;
    CONST TYPE_ASSISTANT_MESSAGE = '助教分成';
    CONST TYPE_MONEY_ARRAY = [
        self::TYPE_REWARD => [
            'value' => self::TYPE_REWARD,
            'memo' => self::TYPE_REWARD_MESSAGE,
        ],

        self::TYPE_FREEZE => [
            'value' => self::TYPE_FREEZE,
            'memo' => self::TYPE_FREEZE_MESSAGE,
        ],

        self::TYPE_WITHDRAWAL => [
            'value' => self::TYPE_WITHDRAWAL,
            'memo' => self::TYPE_WITHDRAWAL_MESSAGE,
        ],

        self::TYPE_TEAM => [
            'value' => self::TYPE_TEAM,
            'memo' => self::TYPE_TEAM_MESSAGE,
        ],

        self::TYPE_MATCH => [
            'value' => self::TYPE_MATCH,
            'memo' => self::TYPE_MATCH_MESSAGE,
        ],

        self::TYPE_UNFREEZE => [
            'value' => self::TYPE_UNFREEZE,
            'memo' => self::TYPE_UNFREEZE_MESSAGE,
        ],
        self::TYPE_ASSISTANT_REWARD => [
            'value' => self::TYPE_ASSISTANT_REWARD,
            'memo' => self::TYPE_ASSISTANT_REWARD_MESSAGE,
        ],
        self::TYPE_ASSISTANT => [
            'value' => self::TYPE_ASSISTANT,
            'memo' => self::TYPE_ASSISTANT_MESSAGE,
        ],
       /* self::TYPE_TEAM_REBATE=>[
            'value' => self::TYPE_TEAM_REBATE,
            'memo' => self::TYPE_TEAM_REBATE_MESSAGE,
        ]*/
    ];

/*

    CONST TYPE_SCORE_TEAM = 1;
    CONST TYPE_SCORE_TEAM_MESSAGE = '组队';
    CONST TYPE_SCORE_MATCH = 2;
    CONST TYPE_SCORE_MATCH_MESSAGE = '竞赛';
    CONST TYPE_SCORE_INVITE= 3;
    CONST TYPE_SCORE_INVITE_MESSAGE= '邀请';
    CONST TYPE_SCORE_INVITED= 4;
    CONST TYPE_SCORE_INVITED_MESSAGE= '被邀请';*/

    /*CONST TYPE_SCORE_ARRAY = [
        self::TYPE_SCORE_TEAM => [
            'value' => self::TYPE_SCORE_TEAM,
            'memo' => self::TYPE_SCORE_TEAM_MESSAGE,
        ],

        self::TYPE_SCORE_MATCH => [
            'value' => self::TYPE_SCORE_MATCH,
            'memo' => self::TYPE_SCORE_MATCH_MESSAGE,
        ],

        self::TYPE_SCORE_INVITE => [
            'value' => self::TYPE_SCORE_INVITE,
            'memo' => self::TYPE_SCORE_INVITE_MESSAGE,
        ],

        self::TYPE_SCORE_INVITED => [
            'value' => self::TYPE_SCORE_INVITED,
            'memo' => self::TYPE_SCORE_INVITED_MESSAGE,
        ],
    ];*/


    CONST CHANGE_TYPE_PAYMENT=1;
    CONST CHANGE_TYPE_PAYMENT_MESSAGE='支出';
    CONST CHANGE_TYPE_INCOME = 2;
    CONST CHANGE_TYPE_INCOME_MESSAGE = '收入';

    CONST CHANGE_TYPE_ARRAY = [
        self::CHANGE_TYPE_PAYMENT=>[
            'value'=>self::CHANGE_TYPE_PAYMENT,
            'memo'=>self::CHANGE_TYPE_PAYMENT_MESSAGE,
        ],
        self::CHANGE_TYPE_INCOME=>[
            'value'=>self::CHANGE_TYPE_INCOME,
            'memo'=>self::CHANGE_TYPE_INCOME_MESSAGE,
        ]
    ];
    public static function getAccount($storeId)
    {
        try {
            $year = date('Y');
            $month = date('m');
            $day = date('d');
            $storeAccount = StoreAccount::where('store_id',$storeId)->find();
            $todayProfit = ProfitStatistics::where('store_id',$storeId)
                ->where('time_type',ProfitStatistics::TIME_TYPE_DAY)
                ->where('year',$year)
                ->where('month',$month)
                ->where('day',$day)
                ->sum('money');

            $storeAccount['todayProfit'] = $todayProfit;
            unset($storeAccount->id);
            unset($storeAccount->store_id);
            unset($storeAccount->status);
            return ['code'=>self::$successCode,'message'=>self::$successMessage,'data'=>$storeAccount];
        }catch (Exception $exception){
            return ['code'=>self::$failCode,'message'=>$exception->getMessage()];
        }
    }
    /**
     * 通过门店id创建门店账户
     * @param int $storeId
     * @param int $merchantId
     * @param bool $trans
     * @return array
     */
    public static function account(int $storeId,int $merchantId,bool $trans=true):array
    {
        $storeAccount = null;
        if ($trans)
            Db::startTrans();
        try {
            if (!StoreAccount::where('store_id',$storeId)->find()) {
                $storeAccount = StoreAccount::create([
                    'store_id'=>$storeId,
                    'merchant_id'=>$merchantId
                ]);
            }
            $storeAccount = StoreAccount::where('store_id',$storeId)->where('merchant_id',$merchantId)->find();
            if ($trans)
                Db::commit();
            self::setStatusCode(self::$successCode);
            self::setMessage(self::$successMessage);
            self::setData($storeAccount);
        }catch (Exception $exception){
            if ($trans)
                Db::rollback();
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage());
        }

        return ['code'=>self::getStatusCode(),'message'=>self::getMessage(),'data'=>self::getData()];
    }

    /**
     * 账户金额变动
     * @param int $merchantId 商户id
     * @param int $storeId  门店id
     * @param float $money 金额
     * @param int $outIn 1=支出,2=收入
     * @param int $datetime 时间戳
     * @param int $detail 1=充值,2=冻结,3=提现,4=组队,5=竞赛,6=购买体验卡,7=解冻
     * @param array $extend [扩展字段]['relation_id'=>$relation_id,'relation_order'=>$relation_order]  relation_id 相关id  relation_order 相关订单号
     * @param boolean $trans 是否开启事务
     * @return array
     */
    public static function money(int $merchantId,int $storeId,float $money,int $outIn,int $datetime,int $detail,array $extend=[],bool $trans=true):array
    {
        $datetime = date('Y-m-d H:i:s',$datetime);
        $result = ['code'=>self::$failCode,'message'=>self::$failMessage];
        if ($trans)
            Db::startTrans();
        try {
            $storeInfo = Store::get($storeId);
            $storeAccount = StoreAccount::where(['store_id'=>$storeId,'merchant_id'=>$merchantId])->find();
            if(!$storeAccount){
                $accountResult = self::account($storeId,$merchantId);
                if ($accountResult['code']==self::$failCode){
                    throw new Exception($accountResult['message']);
                }
                $storeAccount = $accountResult['data'];
            }
            switch ($detail){
                case self::TYPE_REWARD:
                    if(!StoreAccount::where('store_id',$storeId)
                        ->where('merchant_id',$merchantId)
                        ->where('version',$storeAccount->version)
                        ->update([
                        'total' => Db::raw('total + '.$money),
                        'reward_money' => Db::raw('reward_money + '.$money),
                        'total_profit' => Db::raw('total_profit + '.$money),
                        'available_balance' => Db::raw('available_balance + '.$money),
                        'version' => Db::raw('version + 1'),
                    ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(StoreMoneyManager::TYPE_REWARD_MESSAGE,$storeInfo->store_name,$datetime,$money);
                    $result = StoreMoneyManager::StoreMoneyLog($storeAccount,$storeId,$money,StoreMoneyManager::TYPE_INCREASE,StoreMoneyManager::TYPE_REWARD,$message,$extend,false);
                    break;
                case self::TYPE_FREEZE:
                    if(!StoreAccount::where('store_id',$storeId)->where('merchant_id',$merchantId)->where('version',$storeAccount->version)->update([
                        'available_balance' => Db::raw('available_balance - '.$money),
                        'freeze' => Db::raw('freeze + '.$money),
                        'version' => Db::raw('version + 1'),
                    ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(StoreMoneyManager::TYPE_FREEZE_MESSAGE,$storeInfo->store_name,$datetime,$money);
                    $result = StoreMoneyManager::StoreMoneyLog($storeAccount,$storeId,$money,0,StoreMoneyManager::TYPE_FREEZE,$message,$extend,false);
                    break;

                case self::TYPE_WITHDRAWAL:
                    if(!StoreAccount::where('store_id',$storeId)
                        ->where('merchant_id',$merchantId)
                        ->where('freeze','>=',$money)
                        ->where('total','>=',$money)
                        ->where('version',$storeAccount->version)
                        ->update([
                        'total' => Db::raw('total - '.$money),
                        'freeze' => Db::raw('freeze - '.$money),
                        'version' => Db::raw('version + 1'),
                    ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(StoreMoneyManager::TYPE_FREEZE_MESSAGE,$storeInfo->store_name,$datetime,$money);
                    $result = StoreMoneyManager::StoreMoneyLog($storeAccount,$storeId,-$money,StoreMoneyManager::TYPE_DECREASE,StoreMoneyManager::TYPE_WITHDRAWAL,$message,$extend,false);
                    break;
                case self::TYPE_TEAM:
                    if ($outIn==self::CHANGE_TYPE_INCOME){
                        if(!StoreAccount::where('store_id',$storeId)
                            ->where('merchant_id',$merchantId)
                            ->where('version',$storeAccount->version)
                            ->update([
                                'total' => Db::raw('total + '.$money),
                                'available_balance' => Db::raw('available_balance + '.$money),
                                'team_profit'=>Db::raw('team_profit + '.$money),
                                'total_profit'=>Db::raw('total_profit + '.$money),
                                'version' => Db::raw('version + 1')
                            ]))
                        {
                            throw new Exception('账户余额变动失败');
                        }
                        $message = sprintf(StoreMoneyManager::TYPE_TEAM_MESSAGE,$storeInfo->store_name,$datetime,$money);
                        $result = StoreMoneyManager::StoreMoneyLog($storeAccount,$storeId,$money,StoreMoneyManager::TYPE_INCREASE,StoreMoneyManager::TYPE_TEAM,$message,$extend,false);
                    }

                    break;
                case self::TYPE_MATCH:
                    if(!StoreAccount::where('store_id',$storeId)
                        ->where('merchant_id',$merchantId)
                        ->where('version',$storeAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'match_profit'=>Db::raw('match_profit + '.$money),
                            'total_profit'=>Db::raw('total_profit + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(StoreMoneyManager::TYPE_MATCH_MESSAGE,$storeInfo->store_name,$datetime,$money);
                    $result = StoreMoneyManager::StoreMoneyLog($storeAccount,$storeId,$money,StoreMoneyManager::TYPE_INCREASE,StoreMoneyManager::TYPE_MATCH,$message,$extend,false);
                    break;

                case self::TYPE_UNFREEZE:
                    if(!StoreAccount::where('store_id',$storeId)
                        ->where('freeze','>=',$money)
                        ->where('version',$storeAccount->version)
                        ->update([
                            'freeze' => Db::raw('freeze - '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(StoreMoneyManager::TYPE_UNFREEZE_MESSAGE,$storeInfo->store_name,$datetime,$money);
                    $result = StoreMoneyManager::StoreMoneyLog($storeAccount,$storeId,$money,0,StoreMoneyManager::TYPE_UNFREEZE,$message,$extend,false);
                    break;
                case self::TYPE_ASSISTANT:
                    if(!StoreAccount::where('store_id',$storeId)
                        ->where('merchant_id',$merchantId)
                        ->where('version',$storeAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'reward_money' => Db::raw('reward_money + '.$money),
                            'total_profit' => Db::raw('total_profit + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(StoreMoneyManager::TYPE_ASSISTANT_MESSAGE,$storeInfo->store_name,$datetime,$money);
                    $result = StoreMoneyManager::StoreMoneyLog($storeAccount,$storeId,$money,StoreMoneyManager::TYPE_INCREASE,StoreMoneyManager::TYPE_ASSISTANT,$message,$extend,false);
                    break;
                case self::TYPE_ASSISTANT_REWARD:
                    if(!StoreAccount::where('store_id',$storeId)
                        ->where('merchant_id',$merchantId)
                        ->where('version',$storeAccount->version)
                        ->update([
                            'total' => Db::raw('total + '.$money),
                            'reward_money' => Db::raw('reward_money + '.$money),
                            'total_profit' => Db::raw('total_profit + '.$money),
                            'available_balance' => Db::raw('available_balance + '.$money),
                            'version' => Db::raw('version + 1'),
                        ])){
                        throw new Exception('账户余额变动失败');
                    }

                    $message = sprintf(StoreMoneyManager::TYPE_ASSISTANT_REWARD_MESSAGE,$storeInfo->store_name,$datetime,$money);
                    $result = StoreMoneyManager::StoreMoneyLog($storeAccount,$storeId,$money,StoreMoneyManager::TYPE_INCREASE,StoreMoneyManager::TYPE_ASSISTANT_REWARD,$message,$extend,false);
                    break;
                default:
                    break;


            }
            if ($result['code']==self::$failCode){
                throw new Exception($result['message']);
            }

            self::setStatusCode(self::$successCode);
            self::setMessage(self::$successMessage);
            if ($trans)
                Db::commit();
        }catch (Exception $exception){
            if ($trans)
                Db::rollback();
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage().$exception->getLine());
        }

        return ['code'=>self::getStatusCode(),'message'=>self::getMessage()];
    }


    /**
     * 获取金额日志
     * @param int $storeId
     * @param int $type
     * @param int $detail
     * @param array $where
     * @param int $page
     * @param int $step
     * @return array
     */
    public static function moneyLog(int $storeId,int $type=0,int $detail=0,array $where = [],int $page=1,int $step=Constant::PAGE_LIMIT):array
    {
        $return = ['total'=>0,'totalPage'=>1,'currentPage'=>$page,'list'=>[]];
        try {
            $start = ($page-1)*$step;
            $total = StoreMoneyLog::where('store_id',$storeId)->where(function ($query) use ($type) {
                if ($type){
                    return $query->where('type',$type);
                }
            })->where(function ($query) use ($detail) {
                if ($detail){
                    return $query->where('detail',$detail);
                }
            })->where(function ($query) use ($where) {
                if ($where){
                    return $query->where($where);
                }
            })->count();

            $data  = StoreMoneyLog::where('store_id',$storeId)->where(function ($query) use ($type) {
               if ($type){
                   return $query->where('type',$type);
               }
            })->where(function ($query) use ($detail) {
                if ($detail){
                    return $query->where('detail',$detail);
                }
            })->where(function ($query) use ($where) {
                if ($where){
                    return $query->where($where);
                }
            })->order('id desc')->limit($start,$step)->select();

            if ($data){
                foreach ($data as $k=>&$v){
                    $v['type_name'] = self::CHANGE_TYPE_ARRAY[$v['type']]['memo'] ?? '不详';
                    $v['detail_name'] = self::TYPE_MONEY_ARRAY[$v['detail']]['memo'] ?? '不详';
                }
            }
            $page = page($total,$step,$page);
            $return['list'] = $data;
            $return = array_merge($return,$page);
        }catch (Exception $exception){
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage());
        }
        return ['code'=>self::getStatusCode(),'message'=>self::getMessage(),'data'=>$return];
    }

    /**
     * 门店等級升級
     * @param int $storeId
     * @param string $type upgrade downgrade
     * @param bool $trans
     * @return array
     */
    public static function LevelUpgrade(int $storeId,string $type='upgrade',bool $trans=true)
    {
        if ($trans)
            Db::startTrans();
        try {
            $storeInfo = Store::where('id',$storeId)->find();
            $currentLevel = $storeInfo['level'];
            $storeAccount = StoreAccount::where('store_id',$storeId)->find();
            if ($type == 'upgrade'){
                $currentCount = bcadd($storeAccount['total_number'],1);
            }else if ($type=='downgrade'){
                $currentCount = bcsub($storeAccount['total_number'],1);
            }
            if ($type=='upgrade'){
                $currentLevelInfo = Level::where('all_count','=',$currentCount)->find();
            }else if ($type=='downgrade'){
                $currentLevelInfo = Level::where('all_count','<=',$currentCount)->order('all_count desc')->find();
            }

            if (isset($currentLevelInfo['vl_id']) && $currentLevelInfo['vl_id'] != $currentLevel){
                Store::where('id',$storeId)->update(['level'=>$currentLevelInfo['vl_id'],'updatetime'=>time()]);
            }

            if ($trans)
                Db::commit();
            self::setStatusCode(self::$successCode);
            self::setMessage(self::$successMessage);
        }catch (Exception $exception){
            if ($trans)
                Db::rollback();
            self::setStatusCode(self::$failCode);
            self::setMessage($exception->getMessage().$exception->getLine());
        }

        return ['code'=>self::getStatusCode(),'message'=>self::getMessage()];
    }

}